/**
 * 
 */
package Verifier.ArithmeticSystem;

import java.math.BigInteger;

/**
 * Represents a field Z_q where q is a prime number which represents the order of the field.
 * 
 * @author Moshe Baavur
 *
 */
public class Field {
	// represents the field's order
	BigInteger fieldOrder;
	
	/**
	 * Creates a field with the passed number as its order.
	 * 
	 * @param fieldOrder The order of the created field. This number cannot be zero or negative.
	 * @throws Exception fieldOrder is zero or negative.
	 */
	public Field(BigInteger fieldOrder) throws Exception {
		// check that the order of the field is a positive number
		if (1 != fieldOrder.signum()) {
			throw new Exception("Field: The order of the field cannot be zero or negative!");
		}
		
		// check that the order is probably prime
		if (false == fieldOrder.isProbablePrime(Verifier.Verifier.NumberOfPrimeTests)) {
			throw new Exception("Field: The order of the field is not prime!");
		}
		
		// the order is positive, save it as a positive number
		this.fieldOrder = fieldOrder;
	}
	
	/**
	 * Returns the order of the field. 
	 * 
	 * @return The order of the field which is the first number in the field which equals to 0 and is not 0.
	 */
	public BigInteger getOrder() {
		return (fieldOrder);
	}
	
	/**
	 * Checks if the specified element is in the field, meaning the element is a non-negative number and lower than the field order. 
	 * 
	 * @param element the element to check.
	 * @return true if and only if the element is a non-negative number which is lower than the field order. 
	 */
	public boolean doesElementBelong(FieldElement element)
	{
		// first, save the big integer representing the element
		BigInteger elementNumber = element.getElement();
		 
		// if the element is negative
		if (-1 == elementNumber.signum())
			return (false);
		 
		// now, check if elementNumber < fieldOrder 
		return (1 == fieldOrder.compareTo(elementNumber));
	}
	
	/**
	 * Compare this to obj. They are equal only if obj is of type Field and their orders are equal.
	 * 
	 * @param obj the object to compare to this.
	 * @return boolean true if and only if obj is of type Field and its order is equal to this.
	 */
	@Override
	public boolean equals(Object obj) {
		// if the object is a field, then compare them using their order and not the address
		if (obj instanceof Field) {
			BigInteger otherFieldOrder = ((Field)obj).fieldOrder;
			return (fieldOrder.equals(otherFieldOrder));
		}
		// otherwise, they are not equal
		return (false);
	}
}
